﻿using System;
using System.Collections;
using System.Linq;
using System.Windows.Forms;

namespace ThreadSafeControls {
    partial class ThreadSafeListView {
        public sealed class ListViewItemCollection : IList {

            private readonly ThreadSafeListView _listView;
            private object _syncRoot;

            internal ListViewItemCollection(ThreadSafeListView listView) {
                if (listView == null)
                    throw new ArgumentNullException("listView");

                _listView = listView;
            }

            public int Count {
                get { return _listView.ReturnAsync<int>(c => c.Items.Count); }
            }

            public ThreadSafeListViewItem this[int index] {
                get { return _listView.ReturnAsync<ListViewItem>(c => c.Items[index]).AsThreadSafe(_listView); }
                set { _listView.UpdateAsync(c => c.Items[index] = value.ListViewItem); }
            }

            public ThreadSafeListViewItem this[string key] {
                get { return _listView.ReturnAsync<ListViewItem>(c => c.Items[key]).AsThreadSafe(_listView); }
            }

            public ThreadSafeListViewItem Add(string text) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Add(text)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Add(ListViewItem value) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Add(value)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Add(string text, int imageIndex) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Add(text, imageIndex)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Add(string text, string imageKey) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Add(text, imageKey)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Add(string key, string text, int imageIndex) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Add(key, text, imageIndex)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Add(string key, string text, string imageKey) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Add(key, text, imageKey)).AsThreadSafe(_listView);
            }

            public void AddRange(ListViewItem[] items) {
                _listView.UpdateAsync(c => c.Items.AddRange(items));
            }

            public void Clear() {
                _listView.UpdateAsync(c => c.Items.Clear());
            }

            public bool Contains(ListViewItem item) {
                return _listView.ReturnAsync<bool>(c => c.Items.Contains(item));
            }

            public bool ContainsKey(string key) {
                return _listView.ReturnAsync<bool>(c => c.Items.ContainsKey(key));
            }

            public void CopyTo(Array dest, int index) {
                _listView.UpdateAsync(c => c.Items.CopyTo(dest, index));
            }

            public ThreadSafeListViewItem[] Find(string key, bool searchAllSubItems) {
                return _listView.ReturnAsync<ListViewItem[]>(c => c.Items.Find(key, searchAllSubItems))
                    .Select(item => item.AsThreadSafe(_listView))
                    .ToArray();
            }

            public int IndexOf(ListViewItem item) {
                return _listView.ReturnAsync<int>(c => c.Items.IndexOf(item));
            }

            public int IndexOfKey(string key) {
                return _listView.ReturnAsync<int>(c => c.Items.IndexOfKey(key));
            }

            public ThreadSafeListViewItem Insert(int index, string text) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Insert(index, text)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Insert(int index, ListViewItem item) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Insert(index, item)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Insert(int index, string text, int imageIndex) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Insert(index, text, imageIndex)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Insert(int index, string text, string imageKey) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Insert(index, text, imageKey)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Insert(int index, string key, string text, int imageIndex) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Insert(index, key, text, imageIndex)).AsThreadSafe(_listView);
            }

            public ThreadSafeListViewItem Insert(int index, string key, string text, string imageKey) {
                return _listView.ReturnAsync<ListViewItem>(c => c.Items.Insert(index, key, text, imageKey)).AsThreadSafe(_listView);
            }

            public void Remove(ListViewItem item) {
                _listView.UpdateAsync(c => c.Items.Remove(item));
            }

            public void RemoveAt(int index) {
                _listView.UpdateAsync(c => c.Items.RemoveAt(index));
            }

            public void RemoveByKey(string key) {
                _listView.UpdateAsync(c => c.Items.RemoveByKey(key));
            }

            public IEnumerator GetEnumerator() {
                return _listView.ReturnAsync<IEnumerator>(c => c.Items.GetEnumerator());
            }

            #region Explicit Interface Members

            object IList.this[int index] {
                get { return this[index]; }
                set { _listView.UpdateAsync(c => ((IList)c.Items)[index] = value); }
            }

            bool IList.IsFixedSize {
                get { return false; }
            }

            bool IList.IsReadOnly {
                get { return false; }
            }

            bool ICollection.IsSynchronized {
                get { return false; }
            }

            object ICollection.SyncRoot {
                get { return _syncRoot ?? (_syncRoot = new object()); }
            }

            int IList.Add(object value) {
                return _listView.ReturnAsync(c => ((IList)c.Items).Add(value));
            }

            bool IList.Contains(object value) {
                return _listView.ReturnAsync(c => ((IList)c.Items).Contains(value));
            }

            int IList.IndexOf(object value) {
                return _listView.ReturnAsync(c => ((IList)c.Items).IndexOf(value));
            }

            void IList.Insert(int index, object value) {
                _listView.UpdateAsync(c => ((IList)c.Items).Insert(index, value));
            }

            void IList.Remove(object value) {
                _listView.UpdateAsync(c => ((IList)c.Items).Remove(value));
            }

            #endregion

        }
    }
}
